import numpy as np


# 激活函数（符号函数）
def sign(x):
    return np.where(x >= 0, 1, -1)


# 感知机类
class Perceptron:
    def __init__(self, learning_rate=0.01, n_iters=1000):
        self.lr = learning_rate
        self.n_iters = n_iters
        self.activation_func = sign
        self.weights = None
        self.bias = None

    def fit(self, X, y):
        n_samples, n_features = X.shape

        # 初始化权重和偏置
        self.weights = np.zeros(n_features)
        self.bias = 0

        y_ = np.array([1 if i > 0 else 0 for i in y])  # 将类别标签转换为1和0

        for _ in range(self.n_iters):
            for idx, x_i in enumerate(X):
                condition = y_[idx] * (np.dot(x_i, self.weights) - self.bias) <= 0
                if condition:
                    self.weights += self.lr * y_[idx] * x_i
                    self.bias -= self.lr * y_[idx]

    def predict(self, X):
        linear_output = np.dot(X, self.weights) - self.bias
        y_pred = self.activation_func(linear_output)
        return y_pred

    # 示例数据


X = np.array([[0, 0],  # 土豆，颜色：棕色（0），形状：圆形（0）
              [0, 0],  # 土豆
              [1, 1],  # 苹果，颜色：非棕色（1），形状：非圆形（1）
              [1, 1]])  # 苹果
y = np.array([-1, -1, 1, 1])  # 类别标签，-1表示土豆，1表示苹果

# 初始化感知机并训练
p = Perceptron(learning_rate=0.1, n_iters=1000)
p.fit(X, y)

# 预测
predictions = p.predict(X)
print("Predictions:", predictions)

# 检查预测是否准确
accuracy = np.mean(predictions == np.array([1 if i > 0 else -1 for i in y]))
print("Accuracy:", accuracy)

# 假设我们有一个新的样本，我们知道它的颜色是非棕色的（1），形状是非圆形的（1）
new_sample = np.array([[1, 1]])

# 使用已经训练好的感知机进行预测
predicted_class = p.predict(new_sample)

# 输出预测结果
print("Predicted class for the new sample:", predicted_class)

# 由于我们使用的是符号函数作为激活函数，并且类别标签被转换为1和-1，
# 我们可能需要将预测结果转换回更容易理解的标签（例如，“苹果”或“土豆”）
if predicted_class[0] == 1:
    print("The new sample is predicted to be an apple.")
else:
    print("The new sample is predicted to be a potato.")